Start of report Skip to Example 1 Skip to Example 3 Skip to Example 4 Skip to Example 5 Reference Page

## General Elliptic Integral of the Second Kind (s21dac) |

Here we show how to write an interface to a NAG C Library function with complex input and return values.

- Function prototype from the NAG C Library Manual
- C Interface
- Compiling with the builder script
- Example of calling the function

### Function prototype from the NAG C Library Manual

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

#include <nag.h> #include <nags.h> Complex nag_elliptic_integral_f(Complex z, double akp, double a, double b, NagError *fail)

This function takes an input variable of type*Complex*and returns the evaluation of the general elliptic integral of the second kind from zero up to this input value*z*.### C Interface

Here is the source code of our interface written in C nag_intext2.c:

/* Example 2 ========= Shows how to implement a simple NAG routine. Using complex types and variable left hand side arguments is demonstrated. */ #include "stack-c.h" #undef Complex #define Complex NagComplex #include <nag.h> #include <nags.h> #define SciComplex doublecomplex int nag_intext2(char *fname) { // This is how you could call this function from in Scilab // y = nag_elliptic_integral_f_eqn(z,akp,a,b) int m1,n1,l1; int m2,n2,l2; int m3,n3,l3; int m4,n4,l4; int m5,n5,l5; int l6; double akp, a, b; SciComplex z, y; NagComplex z_nag, y_nag; NagError ifail; // define minimum and maximum left and right hand arguments int minlhs=1, minrhs=4, maxlhs=2, maxrhs=4; Nbvars = 0; CheckRhs(minrhs, maxrhs); CheckLhs(minlhs,maxlhs); // Initialise ifail INIT_FAIL(ifail); // Get the right hand side variables 1 to 4 GetRhsVar(1, "z", &m1, &n1, &l1); GetRhsVar(2, "d", &m2, &n2, &l2); GetRhsVar(3, "d", &m3, &n3, &l3); GetRhsVar(4, "d", &m4, &n4, &l4); // d stands for double, r for float (real), i for integer and // c for character string and z for complex if (m1!=1 || n1!=1) { sciprint("%s: Dimension should be 1x1 for arg 1\r\n",fname); Error(999); return(0); } if (m2!=1 || n2!=1) { sciprint("%s: Dimension should be 1x1 for arg 2\r\n",fname); Error(999); return(0); } if (m3!=1 || n3!=1) { sciprint("%s: Dimension should be 1x1 for arg 3\r\n",fname); Error(999); return(0); } if (m4!=1 || n4!=1) { sciprint("%s: Dimension should be 1x1 for arg 4\r\n",fname); Error(999); return(0); } // Create the 5th and 6th variable for the left hand side output variables CreateVar(5, "i", &m1, &n1, &l5); CreateVar(6, "z", &m1, &n1, &l6); // Retrieve the input data from the various stacks. zstk() is for complex, stk() // is for double, sstk() is for reals, cstk() is for characters and istk() is // for integers. z = *zstk(l1); akp = *stk(l2); a = *stk(l3); b = *stk(l4); // Convert Scilab to NAG complex types z_nag.re = z.r; z_nag.im = z.i; // Run the NAG function s21dac y_nag = nag_elliptic_integral_f(z_nag,akp,a,b,&ifail); // Convert NAG to Scilab complex types y.r = y_nag.re; y.i = y_nag.im; // Put the outputs of the NAG function into the created variables 5 and 6 *zstk(l6) = y; *istk(l5) = ifail.code; // Point the ouput of the Scilab function to the variables 5 and 6. The order matters // here, as we want 6 to be the first variable out, and 5 to be the second optional // output variable. LhsVar(1) = 6; LhsVar(2) = 5; return(0); }

Points to note about this code:

- The Scilab complex type is originally
*doublecomplex*and is a struct with*.r*being the real part and*.i*being the imaginary part. The NAG Complex type on the other hand stores the real part and imaginary part as*.re*and*.im*. Therefore we have to convert between the two different Complex types in this interface. - Contained in the code are some useful comments for when retrieving the different data types using the
*GetRhsVar*and when retrieving from the Scilab stack. This information can also be found on the reference page. - The interface doesn't take in the input arguments of the function as its arguments, but only
takes
*fname*the name of the function in Scilab. In this example we have chosen fname to be the same as the NAG C library name. - The Scilab function GetRhsVar is used to retrieve the input arguments of
*fname* - CreateVar creates a variable into which the NAG output is placed
- The interface doesn't actually return the outputs of the function
*fname*- instead the Scilab array LhsVar stores the variable numbers that are stored on Scilab's stack*zstk()*

- The Scilab complex type is originally
### Compiling with the Builder Script

To compile and link this function, you can run the build script nag_builder2.sce which links this interface to the function name

*fname*that will be seen in Scilab. This must be run in the same directory as the interface file, and when run successfully, generates a loader script*loader.sce*that needs to be executed in order to dynamically link the newly created library into Scilab.exec nag_builder2.sce exec loader.sce

### Calling the function

If the function built and the loader.sce file loaded the function without problem, then we can use the function within Scilab, either on the command-line or in a script. Here we run the example script, nag_example2.sce.

--> exec nag_example2.sce y = 1.9712598 + 0.5053832i

*Tip*: If you get any error messages in Scilab check the troubleshooting section.

Start of report Skip to Example 1 Skip to Example 3 Skip to Example 4 Skip to Example 5 Reference Page