# Calling NAG Library Routines from Octave - Example 2

## 3.2. Example 2

### Scaled complex complement of error function, exp(-z2)erfc(-iz) - nag_complex_erfc (s15ddc) routine

Here we show how to call a function with complex input and output values.

1. ### Function prototype from the NAG C Library Manual

According to the C Library Manual, the prototype for function s15ddc looks like this:

  #include <nag.h>
#include <nags.h>

Complex nag_complex_erfc(Complex z, NagError *fail);


The function takes two arguments. The first one is of type Complex and is the argument z of the function. The second argument to s15ddc is the error handling argument fail which is of type NagError. See the NAG C Library Manual for more information about the NagError type. To keep things simple we are not going to try to pass the contents of the NagError structure back to Octave. Instead, we will return only integer value of fail.code.

2. ### C++ function

Here is the source code of our C++ function nag_cmplx_erfc.cc:

#undef Complex
#define Complex OctComplex
#include <octave/oct.h>
#undef Complex
#define Complex NagComplex
#define MatrixType NagMatrixType
#include <nag.h>
#include <nags.h>

DEFUN_DLD (nag_cmplx_erfc, args, ,
"Calls nag_complex_erfc (s15ddc), which computes values \n\
of the function w(z)=e^(-z^2)erfc-iz, for complex z.\n")
{
// Variable to store function output values
octave_value_list retval;
// Retrieve input arguments from args
OctComplex z = args(0).complex_value();
// Local variables
NagError fail;
INIT_FAIL(fail);
OctComplex w;
NagComplex z_nag, w_nag;
// Copy the input OctComplex variable into NagComplex one
z_nag.re = z.real();
z_nag.im = z.imag();

// Call NAG routine like in C
w_nag = nag_complex_erfc(z_nag,&fail);

// Copy the output NagComplex variable into OctComplex one
w.real() = w_nag.re;
w.imag() = w_nag.im;
// Assign output arguments to retval
retval(0) = w;
retval(1) = fail.code;

return retval;
}


• For clarity, the input arguments type checking and error message printing have been omitted in the article text. However, they have been added to the file you can download from this site.
• Complex and MatrixType types are defined in Octave and NAG header files. In this example we are using Complex type, so we need to rename both of its definitions. We overwrite it with OctComplex, before including oct.h, and with NagComplex, before including nag.h. We are not using MatrixType, so it can be renamed in one place only, like in the previous example.
• NAG and Octave Complex types are defined differently, so we cannot pass an Octave complex variable directly to a NAG routine. We create a local variable of type NagComplex and make a copy of the Octave variable. We do the opposite with the complex type result from the NAG routine.
• The third DEFUN_DLD argument (nargout) is not used, so it is omitted in order to avoid the warning from gcc about an unused function parameter.
3. ### Compiling into Oct-File

To compile the C++ function into oct-files, we use the mkoctfile script supplied with Octave:

  % mkoctfile nag_cmplx_erfc.cc -L/opt/NAG/cll6a08dg/lib -lnagc_nag -I/opt/NAG/cll6a08dg/include


where:

• the -L switch tells the C compiler where to look for NAG C Library installed on your system;
• -lnagc_nag is the name of the NAG C Library;
• the -I switch should be followed by the location of NAG C Library header files.
4. ### Calling the function

Assuming that all has gone well, we can call the function as if it was part of Octave itself, i.e. either from the Octave command line or from within an Octave program. An example call may be:

octave:1> z=complex(-3.01,0.75)
z = -3.01000 + 0.75000i
octave:2> [w,ifail]=nag_cmplx_erfc(z)
w =  0.052156 - 0.183776i
ifail = 0


(If you get an error message saying that a library cannot be located, see the tip given in Example 1).