関数が返す複素数値は、C と Fortran では異なる方法で処理されます。BLAS は Fortran スタイルであるため、複素数値を返す BLAS 関数への C からの呼び出しを処理するときは注意が必要です。ただし、通常の関数呼び出しに加えて、Fortran では関数をサブルーチンのように呼び出すことができるため、関数が C プログラムから呼び出されたときに複素数値を正しく返すメカニズムが提供されます。Fortran 関数がサブルーチンとして呼び出されると、戻り値は呼び出しシーケンスの最初のパラメーターになります。この機能を使用すると、C から BLAS 関数を呼び出すことができます。
以下の例は、Fortran 関数のサブルーチンとしての呼び出しを C からの呼び出しに変換する方法を示しています (隠しパラメーター result が表示されている点に注意):
通常の Fortran 関数呼び出し: result = cdotc( n, x, 1, y, 1 )
関数をサブルーチンとして呼び出す: call cdotc( result, n, x, 1, y, 1)
関数をC から呼び出す: cdotc( &result, &n, x, &one, y, &one )
インテル® oneAPI マス・カーネル・ライブラリー (インテル® oneMKL) には、Fortran スタイル (大文字と小文字を区別しない) BLAS に大文字、小文字、末尾にアンダースコアが付いた小文字のエントリーポイントがあります。このため、cdotc、cdotc_、および CDOTC はすべて等価です。
上記の例は、C および C++ アプリケーションから複素数値を返すレベル 1 BLAS 関数を呼び出す方法の 1 つを示しています。もっと簡単な方法は、CBLAS インターフェイスを使用することです。たとえば、次のように CBLAS インターフェイスを使用して同じ関数を呼び出すことができます。
cblas_cdotc( n, x, 1, y, 1, &result )
この場合、複素数値は引数リストの最後になります。
次の例は、C および C++ からの Fortran スタイルの BLAS インターフェイスと、CBLAS (C 言語) インターフェイスの使用方法を示しています。
次の例は、C プログラムから複素レベル 1 BLAS 関数 zdotc() を呼び出す方法を表しています。この関数は、2 つの倍精度複素数ベクトルのドット積を計算します。
この例では、複素数タイプのドット積が構造体 c に返されます。
#include "mkl.h"
#define N 5
int main()
{
int n = N, inca = 1, incb = 1, i;
MKL_Complex16 a[N], b[N], c;
for( i = 0; i < n; i++ )
{
a[i].real = (double)i; a[i].imag = (double)i * 2.0;
b[i].real = (double)(n - i); b[i].imag = (double)i * 2.0;
}
zdotc( &c, &n, a, &inca, b, &incb );
printf( "The complex dot product is: ( %6.2f, %6.2f)\n", c.real, c.imag );
return 0;
}
この例では、大きなデータサイズの複素ドット積が構造体 c に返されます。
#include "mkl.h"
#define N 5
int main()
{
MKL_INT64 n = N, inca = 1, incb = 1, i;
MKL_Complex16 a[N], b[N], c;
for( i = 0; i < n; i++ )
{
a[i].real = (double)i; a[i].imag = (double)i * 2.0;
b[i].real = (double)(n - i); b[i].imag = (double)i * 2.0;
}
zdotc_64( &c, &n, a, &inca, b, &incb );
printf( "The complex dot product is: ( %6.2f, %6.2f)\n", c.real, c.imag );
return 0;
}
以下は C++ 実装です。
#include <complex>
#include <iostream>
#define MKL_Complex16 std::complex<double>
#include "mkl.h"
#define N 5
int main()
{
int n, inca = 1, incb = 1, i;
std::complex<double> a[N], b[N], c;
n = N;
for( i = 0; i < n; i++ )
{
a[i] = std::complex<double>(i,i*2.0);
b[i] = std::complex<double>(n-i,i*2.0);
}
zdotc(&c, &n, a, &inca, b, &incb );
std::cout << "The complex dot product is: " << c << std::endl;
return 0;
}
この例では CBLAS を使用します。
#include <stdio.h>
#include "mkl.h"
typedef struct{ double re; double im; } complex16;
#define N 5
int main()
{
int n, inca = 1, incb = 1, i;
complex16 a[N], b[N], c;
n = N;
for( i = 0; i < n; i++ )
{
a[i].re = (double)i; a[i].im = (double)i * 2.0;
b[i].re = (double)(n - i); b[i].im = (double)i * 2.0;
}
cblas_zdotc_sub(n, a, inca, b, incb, &c );
printf( "The complex dot product is: ( %6.2f, %6.2f)\n", c.re, c.im );
return 0;
}