C interface user’s guide (for XLPack 5.2)

What is “C interface”

With the C interface software you will be able to do the followings:

  • You can use the numerical calculation function module of XLPack (or XLPack Lite) from your C/C++ program.
  • The program developed by using the C interface library can run on the personal computer in which XLPack (or XLPack Lite) is installed.
  • Standard C interface LAPACKE/CBLAS is supported for LAPACK/BLAS routines.

C interface library software can be downloaded from download page.

Terms of use of this software

Please follow the following conditions when using.

  • All the rights to this product are the sole property of K Technologies.
  • This software provides the internal interface in as-is condition. It has not been thoroughly tested under all conditions. Therefore, the function, performance, or reliability of this software are not guaranteed.
  • This software must be used under the responsibility of the user. There is no warranty as to any damage caused as a result of using the software. Support services are not provided for this software.
  • Redistribution of this software in any format is prohibited.

System requirements

This software has been developed for the two types of compilers (MSC (conventional Microsoft C/C++ compiler) and Clang/C2 (C/C++ compiler supporting C99 standard)) included in Microsoft Visual Studio 2017. It has been tested by using version 15.9.7.

Usage and notes

C interface functions can be used by linking XLPack.lib (XLPack_32.lib for 32 bit programs). The header file is cnumlib.h. For XLPack Lite, XLPack_Lite.lib (XLPack_Lite_32.lib for 32 bit) and cnumlib_lite.h can be used.

The complex number operators are not supported by MSC. In order to complement for it, category A4 functions are provided.

The functions returning complex numbers cannot be used in C++ (e.g. zdotu, cgam, etc.). The subroutine versions (e.g. zdotu_sub, cgam_sub, etc.) are provided as the alternatives.

Please note the notations of two dimensional array and complex numbers in the reference manual.

  • In the case of Clang, variable length two dimensional arrays are used for the two dimensional array arguments. However, one dimensional arrays are used in the case of MSC and C++. As the manual is written for the former, in the latter case please interpret accordingly.
    Example – “double a[][lda]” in the manual should be interpreted as “double a[]” when using MSC. Please refer to the example codes below.
  • “doublecomplex” type is used in the manual. It is equivalent to “double _Complex” for Clang, “_Dcomplex” for MSC, and “complex<double>” for C++.

LAPACKE and CBLAS

LAPACKE and CBLAS functions are supported by this software. They can be used by linking Lapacke.lib (Lapacke_32.lib for 32 bit) in addition to the C interface library. The header files are lapacke.h and cblas.h. For XLPack Lite, Lapacke_Lite.lib (Lapacke_Lite_32.lib for 32 bit) and lapacke_lite.h are provided.

The LAPACKE and CBLAS functions corresponding to the Lapack/BLAS functions included in XLPack are supported.

Supported LAPACKE/CBLAS functions

(*) shows the functions which are supported for XLPack Lite.

cblas_drotg cblas_drotmg cblas_drot cblas_drotm cblas_dswap cblas_dscal
cblas_dcopy cblas_daxpy cblas_ddot cblas_dsdot cblas_dnrm2 cblas_dasum
cblas_idamax
cblas_dgemv cblas_dgbmv cblas_dger cblas_dsbmv cblas_dspmv cblas_dspr
cblas_dspr2 cblas_dsymv cblas_dsyr cblas_dsyr2 cblas_dtbmv cblas_dtbsv
cblas_dtpmv cblas_dtpsv cblas_dtrmv cblas_dtrsv
cblas_dgemm cblas_dsymm cblas_dsyrk cblas_dsyr2k cblas_dtrmm cblas_dtrsm

cblas_zswap cblas_zscal cblas_zdscal cblas_zcopy cblas_zaxpy cblas_zdotu_sub
cblas_zdotc_sub cblas_dznrm2 cblas_dzasum cblas_izamax
cblas_zgemv cblas_zgbmv cblas_zhemv cblas_zhbmv cblas_zhpmv cblas_ztrmv
cblas_ztbmv cblas_ztpmv cblas_ztrsv cblas_ztbsv cblas_ztpsv cblas_zgeru
cblas_zgerc cblas_zher cblas_zher2 cblas_zhpr cblas_zhpr2
cblas_zgemm cblas_zsymm cblas_zhemm cblas_zherk cblas_zher2k cblas_ztrmm
cblas_ztrsm cblas_zsyrk cblas_zsyr2k

LAPACKE_ddisna LAPACKE_dgbcon LAPACKE_dgbsv LAPACKE_dgbsvx LAPACKE_dgbtrf
LAPACKE_dgbtrs LAPACKE_dgecon(*) LAPACKE_dgees LAPACKE_dgeesx LAPACKE_dgeev
LAPACKE_dgeevx LAPACKE_dgejsv LAPACKE_dgelqf LAPACKE_dgels(*) LAPACKE_dgelss
LAPACKE_dgelsy LAPACKE_dgeqp3 LAPACKE_dgeqrf LAPACKE_dgesv(*) LAPACKE_dgesvd
LAPACKE_dgesvdx LAPACKE_dgesvj LAPACKE_dgesvx LAPACKE_dgetrf LAPACKE_dgetri
LAPACKE_dgetrs LAPACKE_dgges LAPACKE_dggesx LAPACKE_dggev LAPACKE_dggevx
LAPACKE_dggglm LAPACKE_dgglse LAPACKE_dggsvd3 LAPACKE_dgtcon LAPACKE_dgtsv
LAPACKE_dgtsvx LAPACKE_dgttrf LAPACKE_dgttrs LAPACKE_dlamch(*) LAPACKE_dlange(*)
LAPACKE_dlansy(*) LAPACKE_dlantr LAPACKE_dorglq LAPACKE_dorgqr LAPACKE_dormlq
LAPACKE_dormqr LAPACKE_dpbcon LAPACKE_dpbsv LAPACKE_dpbsvx LAPACKE_dpbtrf
LAPACKE_dpbtrs LAPACKE_dpocon(*) LAPACKE_dposv(*) LAPACKE_dposvx LAPACKE_dpotrf
LAPACKE_dpotri LAPACKE_dpotrs LAPACKE_dppcon LAPACKE_dppsv LAPACKE_dppsvx
LAPACKE_dpptrf LAPACKE_dpptri LAPACKE_dpptrs LAPACKE_dptcon LAPACKE_dptsv
LAPACKE_dptsvx LAPACKE_dpttrf LAPACKE_dpttrs LAPACKE_dsbev LAPACKE_dsbevx
LAPACKE_dsbgv LAPACKE_dsbgvx LAPACKE_dsgesv LAPACKE_dspcon LAPACKE_dspev
LAPACKE_dspevx LAPACKE_dspgv LAPACKE_dspgvx LAPACKE_dsposv LAPACKE_dspsv
LAPACKE_dspsvx LAPACKE_dsptrf LAPACKE_dsptri LAPACKE_dsptrs LAPACKE_dstev
LAPACKE_dstevx LAPACKE_dsycon LAPACKE_dsyev(*) LAPACKE_dsyevx LAPACKE_dsygv
LAPACKE_dsygvx LAPACKE_dsysv LAPACKE_dsysvx LAPACKE_dsytrf LAPACKE_dsytri
LAPACKE_dsytrs LAPACKE_dtbcon LAPACKE_dtbtrs LAPACKE_dtpcon LAPACKE_dtptri
LAPACKE_dtptrs LAPACKE_dtrcon LAPACKE_dtrtri LAPACKE_dtrtrs LAPACKE_dtrttf
LAPACKE_dlatms

LAPACKE_slamch

LAPACKE_zcgesv LAPACKE_zcposv LAPACKE_zgbcon LAPACKE_zgbsv LAPACKE_zgbsvx
LAPACKE_zgbtrf LAPACKE_zgbtrs LAPACKE_zgecon LAPACKE_zgees LAPACKE_zgeesx
LAPACKE_zgeev LAPACKE_zgeevx LAPACKE_zgejsv LAPACKE_zgelqf LAPACKE_zgels
LAPACKE_zgelss LAPACKE_zgelsy LAPACKE_zgeqp3 LAPACKE_zgeqrf LAPACKE_zgesv
LAPACKE_zgesvd LAPACKE_zgesvdx LAPACKE_zgesvj LAPACKE_zgesvx LAPACKE_zgetrf
LAPACKE_zgetri LAPACKE_zgetrs LAPACKE_zgges LAPACKE_zggesx LAPACKE_zggev
LAPACKE_zggevx LAPACKE_zggglm LAPACKE_zgglse LAPACKE_zggsvd3 LAPACKE_zgtcon
LAPACKE_zgtsv LAPACKE_zgtsvx LAPACKE_zgttrf LAPACKE_zgttrs LAPACKE_zhbev
LAPACKE_zhbevx LAPACKE_zhbgv LAPACKE_zhbgvx LAPACKE_zhecon LAPACKE_zheev
LAPACKE_zheevx LAPACKE_zhegv LAPACKE_zhegvx LAPACKE_zhesv LAPACKE_zhesvx
LAPACKE_zhetrf LAPACKE_zhetri LAPACKE_zhetrs LAPACKE_zhpcon LAPACKE_zhpev
LAPACKE_zhpevx LAPACKE_zhpgv LAPACKE_zhpgvx LAPACKE_zhpsv LAPACKE_zhpsvx
LAPACKE_zhptrf LAPACKE_zhptri LAPACKE_zhptrs LAPACKE_zlange LAPACKE_zlanhe
LAPACKE_zlansy LAPACKE_zlantr LAPACKE_zpbcon LAPACKE_zpbsv LAPACKE_zpbsvx
LAPACKE_zpbtrf LAPACKE_zpbtrs LAPACKE_zpocon LAPACKE_zposv LAPACKE_zposvx
LAPACKE_zpotrf LAPACKE_zpotri LAPACKE_zpotrs LAPACKE_zppcon LAPACKE_zppsv
LAPACKE_zppsvx LAPACKE_zpptrf LAPACKE_zpptri LAPACKE_zpptrs LAPACKE_zptcon
LAPACKE_zptsv LAPACKE_zptsvx LAPACKE_zpttrf LAPACKE_zpttrs LAPACKE_zspcon
LAPACKE_zspsv LAPACKE_zspsvx LAPACKE_zsptrf LAPACKE_zsptri LAPACKE_zsptrs
LAPACKE_zsycon LAPACKE_zsyr LAPACKE_zsysv LAPACKE_zsysvx LAPACKE_zsytrf
LAPACKE_zsytri LAPACKE_zsytrs LAPACKE_ztbcon LAPACKE_ztbtrs LAPACKE_ztpcon
LAPACKE_ztptri LAPACKE_ztptrs LAPACKE_ztpttf LAPACKE_ztrcon LAPACKE_ztrtri
LAPACKE_ztrtrs LAPACKE_ztrttf LAPACKE_zunglq LAPACKE_zungqr LAPACKE_zunmlq
LAPACKE_zunmqr LAPACKE_zlatms

In the current version, there are some differences on the runtime error handling from the original software as follows.

  • For some errors, error messages are output by the Lapack/BLAS base routines instead of Lapacke/CBLAS routines. In those cases, the displayed argument number may be different from Lapacke/CBLAS.

Please refer to the original sites for the usage of each function.

Description of LAPACKE
LAPACK manual (includes LAPACKE and CBLAS)

Example codes

Examples of use of two dimensional arrays

Solve the following linear equations.

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

(1) Example using MSC

#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;
}

Result
info = 0
x = 0.000000  -1.000000  1.000000

Please note that A is the one dimensional array. Elements must be stored in column-major order (consecutive elements of a column reside next to each other like VBA).

To use two dimensional array, it is necessary to match a data type using cast. However, elements must still be stored in column-major order and then indices of two dimensional array are opposite to mathematical notation.

#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[3], 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, (double *)a, ipiv, ldb, b, &info);
	printf("info = %d\n", info);
	printf("x = %f  %f  %f\n", b[0], b[1], b[2]);
	return 0;
}

(2) Example using Clang/C2

#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;
}

Since Clang supports C99 standard, two dimensional variable length array is used for A. However, elements must be stored in column-major order as well.

(3) Example using Lapacke (MSC)

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

int main(void)
{
	double a[3][3], b[3];
	int n = 3, nrhs = 1, lda = 3, ldb = 3, ipiv[3], 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;

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

A is also one dimensional array in the case of LAPACKE. The added first parameter specifies whether the array is in column-major or row-major order.
By specifying LAPACK_ROW_MAJOR as shown in the example below, indices of A can be conveniently in the same manner as the mathematical notation. However, it should be noted that the array is transposed and copied before and after calculation internally and therefore processing overhead occurs.

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

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

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

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

Examples of use of complex number

Solve the following complex linear equations.

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

(1) Example using MSC

In the case of MSC, Microsoft proprietary type “_Dcomplex” is used for complex numbers.

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

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

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

	info = LAPACKE_zgesv(LAPACK_ROW_MAJOR, n, nrhs, (_Dcomplex *)a, lda, ipiv, b, ldb);
	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)

(2) Example using Clang/C2

In the case of Clang, the C99 standard type “double _Complex” can be used for complex numbers.

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

void zgesv_row(int n, int lda, double _Complex a[][lda], int ipiv[], double _Complex b[], int *info)
{
	int nrhs = 1, ldb = 1;
	*info = LAPACKE_zgesv(LAPACK_ROW_MAJOR, n, nrhs, (double _Complex *)a, lda, ipiv, b, ldb);
}

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

	a[0][0] = 1.66+0.6*I;   a[0][1] = 0.44-0.11*I; a[0][2] = 0.82-0.56*I;
	a[1][0] = 0.47+I;       a[1][1] = 1.23-0.47*I; a[1][2] = -1.72+0.07*I;
	a[2][0] = -1.32-0.61*I; a[2][1] = 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_row(n, lda, a, ipiv, 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;
}

(3) Example using C++

In the case of C++, the standard type “complex<double>” is used for complex numbers.

#include <iostream>
#include "lapacke.h"

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 = 1, ipiv[3], info;

	a[0][0] = 1.66+0.6*i;   a[0][1] = 0.44-0.11*i; a[0][2] = 0.82-0.56*i;
	a[1][0] = 0.47+i;       a[1][1] = 1.23-0.47*i; a[1][2] = -1.72+0.07*i;
	a[2][0] = -1.32-0.61*i; a[2][1] = 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;

	info = LAPACKE_zgesv(LAPACK_ROW_MAJOR, n, nrhs, (complex<double> *)a, lda, ipiv, b, ldb);
	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