Calling NAG Library Routines from Scilab - Example 2

NAG Technical Report 5/2009

Calling NAG Library Routines from Scilab


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

3.2. Example 2

elliptic

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.

Contents

  1. Function prototype from the NAG C Library Manual
  2. C Interface
  3. Compiling with the builder script
  4. Example of calling the function
  1. 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.

  2. 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()
  3. 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
    
  4. 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