As a Senior Technical Consultant for NAG, I answer many customer questions covering many topics. I thought I’d write up one such question I recently received from a NAG C Library user, as the answer may be useful to others.
Q: In looking through the C# associated info, I found many examples of InteropService calls from C# to the C Library (CLW3209DA_nag.dll). Have any examples been posted for the "c05" functions, e.g. nag_zero_cont_func_brent_bsrch(c05agc)?
A: I'm glad you asked! By the time you reach the end of this post, there will be one. J
In working with the NAG C Library from C#, there are three main factors to which we must attend. The first is how to represent the NAG C Library structure types in C#, and for C# this has largely been taken care of for you in NAGCFunctionsAPI.cs.
The second is translating the C library function signature into a C# declaration.
The third is the C# declaration of any required callback functions and the assignment of delegates.
nag_zero_cont_func_brent_bsrch indeed requires a user-supplied callback function “f”, the function for which we want to find a root, whose C prototype is:
double f(double xx, Nag_Comm *comm);
In the containing namespace I declare the corresponding delegate:
public delegate double NAG_C05AGC_FUN(double xx, ref CommStruct comm);
where CommStruct is defined in NAGCFunctionsAPI.cs.
The C prototype for c05agc itself is
void nag_zero_cont_func_brent_bsrch(double *x, double h, double xtol, double ftol, double (*f)(double xx, Nag_Comm *comm), double *a, double *b, Nag_Comm *comm, NagError *fail);
In the relevant class I declare the NAG function thusly:
[DllImport("CLW3209DA_nag")]
public static extern void c05agc(ref double x, double h, double xtol, double ftol, NAG_C05AGC_FUN f, ref double a, ref double b, ref CommStruct user_comm, ref NagError fail);
A C# example console application program for c05agc, similar to the C/C++ program provided by NAG, then might run something like this:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using NagCFunctionsAPI;
namespace c05agce
{
public delegate double NAG_C05AGC_FUN(double xx, ref CommStruct comm);
class Program
{
[DllImport("CLW3209DA_nag")]
public static extern void c05agc(ref double x, double h, double xtol, double ftol, NAG_C05AGC_FUN f, ref double a, ref double b, ref CommStruct user_comm, ref NagError fail);
static void Main(string[] args)
{
NAG_C05AGC_FUN F = new NAG_C05AGC_FUN(f);
NagError fail = new NagError();
fail.char_array = new char[512];
CommStruct user_comm = new CommStruct();
double a=0;
double b=0;
double x = 1.0;
double h = 0.1;
double eps = 1e-05;
double eta = 0.0;
c05agc( ref x, h, eps, eta, F, ref a, ref b, ref user_comm, ref fail);
if (fail.code != 0)
{
string error_message = new string(fail.char_array);
Console.WriteLine(error_message);
}
else
{
Console.WriteLine("Root = {0, 9:f5}", x);
}
}
public static double f(double x, ref CommStruct user_comm)
{
return x - Math.Exp(-x);
}
}
}