Tech Tip: Global data and the NAG Toolbox for MATLAB ®

Some of the most useful and powerful routines in the NAG Toolbox for MATLAB require the user to provide a function, supplied either as an M-file or as a function handle. For example optimisation routines require the user to provide the function to be minimised. Ordinary differential equation routines and quadrature routines also require the user to provide functions in order to specify the problem.

If we take a specific example, that of e04fy, a routine to minimise the sum of squares of m nonlinear functions in n variables, we see can see that it is sometimes necessary to provide information to the user-provided function:

m = int32(15);
x = [0.5;
     1;
     1.5];
y = [0.14,0.18,0.22,0.25,0.29,0.32,0.35,0.39,0.37,0.58,0.73,0.96,1.34,2.10,4.39];
t = [[1.0, 15.0, 1.0],
     [2.0, 14.0, 2.0],
     [3.0, 13.0, 3.0],
     [4.0, 12.0, 4.0],
     [5.0, 11.0, 5.0],
     [6.0, 10.0, 6.0],
     [7.0, 9.0, 7.0],
     [8.0, 8.0, 8.0],
     [9.0, 7.0, 7.0],
     [10.0, 6.0, 6.0],
     [11.0, 5.0, 5.0],
     [12.0, 4.0, 4.0],
     [13.0, 3.0, 3.0],
     [14.0, 2.0, 2.0],
     [15.0, 1.0, 1.0]];

user = {y, t, 3};

[xOut, fsumsq, user, ifail] = e04fy(m, 'e04fy_lsfun1', x, 'user', user);

In this code the 'e04fy_lsfun1' argument means that a user provided function is provided in the M-file e04fy_lsfun1.m:

 function [fvecc, user] = lsfun1(m, n, xc, user)
  fvecc=zeros(m,1);

  % y is in user{1} and t is in user{2}
  for i = 1:m
    fvecc(i) = xc(1) + user{2}(i,1)/(xc(2)*user{2}(i,2)+xc(3)*user{2}(i,3))-...
                user{1}(i);
  end

This is the code we give as our example. You will see that information, the arrays y and t, are bundled up into the parameter 'user' in the calling code and the function lsfun1 receives this as a parameter.

This means of passing information is the most 'stylish' form of programming, but it is not the most efficient. If you have a large amount of information to pass and efficiency is of primary concern, then you might wish to consider using global variables:

global y t;
m = int32(15);
x = [0.5;
     1;
     1.5];
y = [0.14,0.18,0.22,0.25,0.29,0.32,0.35,0.39,0.37,0.58,0.73,0.96,1.34,2.10,4.39];
t = [[1.0, 15.0, 1.0],
     [2.0, 14.0, 2.0],
     [3.0, 13.0, 3.0],
     [4.0, 12.0, 4.0],
     [5.0, 11.0, 5.0],
     [6.0, 10.0, 6.0],
     [7.0, 9.0, 7.0],
     [8.0, 8.0, 8.0],
     [9.0, 7.0, 7.0],
     [10.0, 6.0, 6.0],
     [11.0, 5.0, 5.0],
     [12.0, 4.0, 4.0],
     [13.0, 3.0, 3.0],
     [14.0, 2.0, 2.0],
     [15.0, 1.0, 1.0]];

%user = {y, t, 3};

[xOut, fsumsq, user, ifail] = e04fy(m, 'mod_e04fy_lsfun1', x);

The modied M-file, mod_e04fy_lsfun1.m would then contain:

function [fvecc, user] = lsfun1(m, n, xc, user)
  global y t;
  fvecc=zeros(m,1);

  % y is in user{1} and t is in user{2}
  for i = 1:m
    fvecc(i) = xc(1) + t(i,1)/(xc(2)*t(i,2)+xc(3)*t(i,3))-...
                y(i);
  end

In general global variables are often frowned upon and might be dangerous in multi-threaded or parallel environment but in the context of a single-threaded MATLAB system the performance gains of this mechanism might outweigh any aesthetic objections. Much will depend upon your problem.


For specific technical advice in using NAG's products, please contact our technical experts.

Return to Technical Tips & Hints index page.