Improve Your Math Expressiveness

MATLAB's advanced language features empower scientific programmers.

MATLAB's advanced language features empower scientific programmers.

By Steve Johnson

 
  Dating back to the first FORTRAN compilers,  languages intended to address scientific and engineering problems have been largely driven by performance considerations. As such, they have often lacked the most modern language features and concentrated on performance and optimization.

  Although performance remains important in this area of computing, overall productivity is becoming a more critical success factor. If it takes a month to write and debug a program in a traditional language that runs in an hour, we would be better served by a program that could be written and debugged in a couple of days, but takes three hours to run.

  This article shows how a number of advanced language features improve the ease of use and expressiveness of a widespread engineering language, MATLAB, without undue performance penalty. Of particular note is the ability to treat functions as first-class aspects of the language,  an ability that many conventional general-purpose languages lack.

  Treat Functions as first-class

  Science and engineering have traditionally been heavy users of mathematics, so it is not surprising that science and engineering languages have been greatly influenced by mathematical notation. However, from the first, compromises were made. While mathematics uses mostly single letters for variables and indicates multiplication by concatenation (2xy means 2 times x times y), computer languages introduced the multiplication operator *. The equal sign was hijacked to mean assignment rather than equality. And, in most cases, functions were granted a distinctly secondary role in the language.

  In mathematics, it is quite common to combine functions to create other functions:
      h = f + g.

However, this ability is lacking from most scientific programming languages. The only way to obtain a function is to write it explicitly in code.

  In this article, we show you how to write a function, fadd, at the command line in MATLAB that can take two functions as input and return a function that is their sum. We also show how you can extend MATLAB to include function addition. More importantly, we describe how treating functions as first-class values can make scientific codes easier to write and understand.

  Function handles

  Suppose we have defined a function, payoff, that we want to maximize over the interval from 0 to 1. How do we tell the maximization routine which function we want to maximize?

  In the oldest versions of MATLAB, you passed the function name “payoff” in a character string.   Inside of the maximization routine, a function called feval let the function name in the character string be evaluated repeatedly with various arguments as the maximum was computed. Other routines to find zero crossings or compute integrals also took such character strings, known to MATLAB users as funfuns.

  This approach worked, but had some drawbacks. Most importantly, functions of interest frequently take more than one argument;  the maximization was desired over some of these arguments while other arguments were being treated as parameters.

  Function handles were introduced to eliminate the naming problems that arose from character strings. The function name was simply preceded by an “at” sign—@payoff, creating a “function handle” that could be used to call the function payoff. This handle could be passed to routines and called by feval as well.

  Anonymous functions

  In MATLAB 7, the “extra argument” problem is addressed by allowing the creation of anonymous functions, an extension of function handles. Suppose payoff takes three arguments, and we want to maximize its value over the second argument, while treating the first and third arguments as constant parameters (for example, giving them the values 1.5 and 2.5). Then we can write
     h =  @(x) payoff( 1.5, x, 2.5 );

This produces a function handle, h, which, when invoked with an argument x, performs the indicated call to payoff. It is called an anonymous function because, unlike older function handles, there is no name for this function. At the same time, it becomes possible to call function handles directly, without using feval. So the handle h above could be invoked at the value .75 by writing:
     h(.75)

Anonymous functions let us maximize a function across any argument without having to pass an argument number and auxiliary argument values to the maximization routine.
As another example, we can use an anonymous function to represent the sum of two functions:
     h =  @(x)( sin(x)+cos(x) );

where h is used as a function computing sin +  cos.

 

Most scientific programming languages lack the ability to combine functions.

A first solution for function addition

  Now we can provide our first version of the fadd  function that takes two functions (more strictly, two function handles) and returns a function (handle) for the sum function. We use the above anonymous function that sums two functions and then enclose that in another anonymous function to supply the two function handles:
     fadd =  @(f,g)@(x)(f(x)+g(x));

Using fadd, we can write the example of the last section as:
     h =  fadd( @sin, @cos );

Function factories

  A common pattern in scientific computing is a function factory, which is a function that returns one or more function handles. Interpolation is an excellent example of a function factory. Suppose we have a vector Y of values at points given in another vector X. In MATLAB, we can interpolate a continuous piecewise polynomial function between these points by using the SPLINE function:
     pp =  spline( X, Y );

The result pp gives the coefficients and ranges of the pieces of the interpolating function. To get the value of this interpolating function at x, it is necessary to call another function that depends on pp and x:
     y =  ppval( pp, x );

In the past, it was necessary to generate pp and pass it around to anyone who wished to call the interpolating function. However, using the function factory pattern we can hide the value and existence of pp completely from the end user:
function fh = splinefun( X, Y )
     pp =  spline( X, Y );
     fh =  @(x) ppval( pp, x );
end

The function value fh is a function handle to the interpolating function, and you can write:
     y =  fh( x );

The fact that this function depends on pp is hidden from the user.

  Function addition again

  Instead of the doubly nested anonymous function fadd we gave earlier, we can write a standard function called plus:
     function h = plus( f, g )
     h = @(x)f(x)+g(x);
          end

If we put this function into an appropriate directory (@function_handle) on the MATLAB path, then, by using the standard MATLAB technique for operator overloading, we have just defined addition for function handles. In particular, we can write:
     h =  @sin + @cos;

Similar techniques would allow us to further define
     h = @sin + 1;
and
     h =  @sin * @cos;

Thus, functions can be treated with the same flexibility as variables with little effort. This common operation in mathematics cannot be done in FORTRAN, C++, or Java.

Objects and nested functions

  We can extend arithmetic operations to functions because, at its heart, MATLAB contains a full object system. While not used directly by the majority of MATLAB users, the object system allows MATLAB to interact comfortably with Java and C++, and forms the basis for many powerful applications. Also worthy of mention is another advanced feature, nested functions, which lets you define a function nested within another one. This feature provides a powerful generalization of anonymous functions and delivers both increased expressiveness and higher performance for the advanced programmer.

More power to you

  Science and engineering today are concerned with productivity, correctness, and maintainability as well as performance. Language features that may be seen as “advanced” can help achieve all of these goals. In particular, creating and using functions in ways that mirror similar facilities in mathematics prove extremely powerful.

More Information

MATLAB
The MathWorks
Natick, MA
mathworks.com


Steve Johnson earned his Ph.D. in mathematics,  but has spent his entire career in computing. He worked at Bell Labs and AT&T, where he worked on topics like computer music and VLSI design. He is best known for his work on Unix. In 2002 he became senior fellow at The MathWorks where he helps determine the evolution and technology of the MATLAB programming language. To comment, send an e-mail to DE-Editorsmailto:[email protected].

Acknowledgement:   Thanks are due to my colleagues at The MathWorks, notably Mike Karr and Steve Eddins, who inspired this article.

Share This Article

Subscribe to our FREE magazine, FREE email newsletters or both!

Join over 90,000 engineering professionals who get fresh engineering news as soon as it is published.


About the Author

DE Editors's avatar
DE Editors

DE’s editors contribute news and new product announcements to Digital Engineering.
Press releases may be sent to them via [email protected].

Follow DE

Related Topics

Simulate   All topics
#10125