CNLMath : Introduction : C++ Usage
C++ Usage
IMSL C Numerical Library functions can be used in both C and C++ applications. It is also possible to wrap library functions into C++ classes.
The function imsl_f_int_fcn_sing computes the integral of a user defined function. For C++ usage the user defined function is defined as a member function of the abstract class IntFcnSingFunction defined as follows.
 
#include <imsl.h>
#include <math.h>
#include <stdio.h>
class IntFcnSingFunction
{
public:
virtual float f(float x) = 0;
};
The function imsl_f_int_fcn_sing is wrapped as the C++ class IntFcnSing. This implementation uses the optional argument, IMSL_FCN_W_DATA, to call local_function which in turn calls the method f to evaluate the user defined function. For simplicity, this implementation only wraps a single optional argument, IMSL_MAX_SUBINTER, the maximum number of subintervals. More could be included in a similar manner.
 
#include <imsl.h>
 
class IntFcnSing
{
public:
int max_subinter;
IntFcnSing();
float integrate(IntFcnSingFunction *F, float a, float b);
};
 
static float local_function(float x, void *data)
{
IntFcnSingFunction *F = (IntFcnSingFunction*)data;
return F->f(x);
}
 
IntFcnSing::IntFcnSing()
{
max_subinter = 500;
}
 
float IntFcnSing::integrate(IntFcnSingFunction *F, float a, float b)
{
float result;
 
result = imsl_f_int_fcn_sing(NULL, a, b,
IMSL_FCN_W_DATA, local_function, F,
IMSL_MAX_SUBINTER, max_subinter,
0);
if (imsl_error_type() >= 3)
{
throw imsl_error_message();
}
return result;
}
To use this IntFcnSing the user defined function must be defined as the method f in a class that extends IntFcnSingFunction. The following class, MyClass, defines the function , where a is a parameter.
 
class MyClass : public IntFcnSingFunction
{
public:
MyClass();
float f(double x);
private:
float my_parameter;
};
 
MyClass::MyClass()
{
my_parameter = 5.0;
}
 
float MyClass::f(float x)
{
return exp(x) - my_parameter*x;
}
The following is an example of the use of these classes. Since the C++ throws an exception on fatal or terminal IMSL errors, printing and stopping on these errors is turned off by a call to imsl_error_options. Also, since the user defined function is thread-safe, a call is made to imsl_omp_options to declare this. With this setting, the quadrature code will use OpenMP to evaluate the function in parallel. Both of these calls need be made once per run.
The second part of this example sets the maximum number of subintevals to 5, an unrealistically small number, to show the error handling.
 
int main()
{
imsl_error_options(
IMSL_SET_PRINT, IMSL_FATAL, 0,
IMSL_SET_PRINT, IMSL_TERMINAL, 0,
IMSL_SET_STOP, IMSL_FATAL, 0,
IMSL_SET_STOP, IMSL_TERMINAL, 0,
0);
imsl_omp_options(IMSL_SET_FUNCTIONS_THREAD_SAFE, 1, 0);
 
IntFcnSing *intFcnSing = new IntFcnSing();
MyClass *myClass = new MyClass();
float x = intFcnSing->integrate(myClass, -1.0, 1.0);
printf("Solution in [-1,+1]: %g\n", x);
try {
intFcnSing->max_subinter = 5;
x = intFcnSing -> integrate (myClass, -100.0, 1000.0);
printf("Solution in [-100,1000]: %g\n", x);
} catch(char * exception) {
printf("Exception raised: %s\n", exception);
}
}
Output
 
Integral over [-1,+1] = 2.3504
Exception raised: The maximum number of subintervals allowed "maxsub" = 5 has been reached. Increase "maxsub".