15. Calling XLPack functions from C/C++

Introduction

C/C++ program can call numerical calculation modules of XLPack (or XLPack Lite) through XLPack API (C interface). Please refer to the reference manual for the detail of specifications of C API functions. Please also refer to the sample programs included in the XLPack SDK. Only the major technical points of using API are described here.

Solving system of linear equations by C/C++ program

Example: Solve the following system of linear equations.

  Ax = b
             ( 10  -7   0 )       ( 7 )
  where, A = ( -3   2   6 ),  b = ( 4 )
             (  5  -1   5 )       ( 6 )


The following C program solves the above equations (Visual C is used).

#include <stdio.h>
#include "cnumlib.h"

int main(void)
{
    double a[9] = { 10.0, -3.0, 5.0, -7.0, 2.0, -1.0, 0.0, 6.0, 5.0 };
    double b[3] = { 7.0, 4.0, 6.0 };
    int n = 3, nrhs = 1, lda = 3, ldb = 3, ipiv[3], info;

    dgesv(n, nrhs, lda, a, ipiv, ldb, b, &info);
    printf("info = %d\n", info);
    printf("x = %f  %f  %f\n", b[0], b[1], b[2]);
    return 0;
}

Please note the following points.

  • The header file cnumlib.h ( cnumlib_lite.h for XLPack Lite) is used
  • XLPack.lib (XLPack_32.lib for 32 bit programs) must be linked (XLPack_Lite.lib (XLPack_Lite_32.lib for 32 bit programs) for XLPack Lite)
  • A matrix must be stored in one-dimensional array in column major order (same as VBA and Fortran). If it is stored in the two-dimensional array, use type casting.

Result

info = 0
x = 0.000000  -1.000000  1.000000

Variable-length two-dimensional array is used for the matrix instead of one-dimensional array for Clang compiler (Windows LLVM Clang and macOS Xcode) which supports C99 standard. In that case, the program is as follows.

#include <stdio.h>
#include "cnumlib.h"

int main(void)
{
    double a[3][3], b[3];
    int n = 3, nrhs = 1, lda = 3, ldb = 3, ipiv[10], info;

    a[0][0] = 10.0; a[1][0] = -7.0; a[2][0] = 0.0;
    a[0][1] = -3.0; a[1][1] = 2.0;  a[2][1] = 6.0;
    a[0][2] = 5.0;  a[1][2] = -1.0; a[2][2] = 5.0;
    b[0] = 7.0;
    b[1] = 4.0;
    b[2] = 6.0;

    dgesv(n, nrhs, lda, a, ipiv, ldb, (double (*)[ldb])b, &info);
    printf("info = %d\n", info);
    printf("x = %f  %f  %f\n", b[0], b[1], b[2]);
    return 0;
}

Please note that the notation of matrix in the reference manual follows the latter (Clang, variable-length two-dimensional array). Please replace it to the one-dimensional array in the case of Visual C.
Example – “double a[][lda]” in the manual must be read as “double a[]”.

Please note the following points in the case of C++.

  • cnumlib (cnumlib_lite for XLPack Lite) may be used as the header file
  • Same library as C language must be linked
  • A matrix must be stored in one-dimensional array even in the case of Clang (or use type cast)

Complex number in C/C++ program

Please note the following points when using complex numbers.

  • A data type of complex number is written as doublecomplex in the manual. However, _Dcomplex (Visual C), double _Complex (Clang) or complex<double> (C++) is used for an actual program
  • To make up for lack of complex operators in Visual C, complex arithmetic functions in category A4 are provided
  • XLPack functions which return complex function value are not supported in C++ (such as zdotu, cgam, etc.). For those functions, the alternative subroutines are provided (such as zdotu_sub, cgam_sub, etc.)

Example: Solve the following complex system of linear equations.

  Ax = b
               (  1.66+0.6i   0.44-0.11i    0.82-0.56i )       (  0.9774-0.6426i )
    where, A = (  0.47+i      1.23-0.47i   -1.72+0.07i ),  b = ( -0.0860+1.3628i )
               ( -1.32-0.61i  1.42-0.4i     1.62+0.41i )       ( -0.6599-0.6625i ) 


The following C program solves the above complex equations (Visual C is used).

#include <stdio.h>
#include <complex.h>
#include "cnumlib.h"

int main(void)
{
    _Dcomplex a[9] = {
        cmplx(1.66, 0.6), cmplx(0.47, 1.0), cmplx(-1.32, -0.61),
        cmplx(0.44, -0.11), cmplx(1.23, -0.47), cmplx(1.42, -0.4),
        cmplx(0.82, -0.56), cmplx(-1.72, 0.07), cmplx(1.62, 0.41) };
    _Dcomplex b[3] = {
        cmplx(0.9774, -0.6426), cmplx(-0.086, 1.3628), cmplx(-0.6599, -0.6625) };
    int n = 3, nrhs = 1, lda = 3, ldb = 3, ipiv[3], info;

    zgesv(n, nrhs, lda, a, ipiv, ldb, b, &info);
    printf("info = %d\n", info);
    printf("x = ");
    printf("(%f, %f) ", creal(b[0]), cimag(b[0]));
    printf("(%f, %f) ", creal(b[1]), cimag(b[1]));
    printf("(%f, %f)\n", creal(b[2]), cimag(b[2]));
    return 0;
}

Result

info = 0
x = (0.590000, -0.280000) (-0.200000, -0.040000) (0.240000, -0.490000)

The following is the equivalent C++ program.

#include <iostream>
#include <complex>
#include "cnumlib"

using namespace std;

int main(void)
{
    complex<double> a[3][3], b[3], i(0.0, 1.0);
    int n = 3, nrhs = 1, lda = 3, ldb = 3, ipiv[3], info;

    a[0][0] = 1.66+0.6*i;   a[1][0] = 0.44-0.11*i; a[2][0] = 0.82-0.56*i;
    a[0][1] = 0.47+i;       a[1][1] = 1.23-0.47*i; a[2][1] = -1.72+0.07*i;
    a[0][2] = -1.32-0.61*i; a[1][2] = 1.42-0.4*i;  a[2][2] = 1.62+0.41*i;
    b[0] = 0.9774-0.6426*i;
    b[1] = -0.086+1.3628*i;
    b[2] = -0.6599-0.6625*i;

    zgesv(n, nrhs, lda, (complex<double> *)a, ipiv, ldb, b, info);
    cout << "info = " << info << endl;
    cout << "x = " << b[0] << " " << b[1]  << " "  << b[2] << endl;
    return 0;
}

Result

info = 0
x = (0.59,-0.28) (-0.2,-0.04) (0.24,-0.49)
Top