Developer Guide

Developer Guide for Intel® oneAPI Math Kernel Library macOS*

ID 766688
Date 7/13/2023
Public

A newer version of this document is available. Customers should click here to go to the newest version.

Document Table of Contents
Give Feedback

Calling BLAS Functions that Return the Complex Values in C/C++ Code

Complex values that functions return are handled differently in C and Fortran. Because BLAS is Fortran-style, you need to be careful when handling a call from C to a BLAS function that returns complex values. However, in addition to normal function calls, Fortran enables calling functions as though they were subroutines, which provides a mechanism for returning the complex value correctly when the function is called from a C program. When a Fortran function is called as a subroutine, the return value is the first parameter in the calling sequence. You can use this feature to call a BLAS function from C.

The following example shows how a call to a Fortran function as a subroutine converts to a call from C and the hidden parameter result gets exposed:

Normal Fortran function call:                   result = cdotc( n, x, 1, y, 1 )

A call to the function as a subroutine:  call cdotc( result, n, x, 1, y, 1)

A call to the function from C:                  cdotc( &result, &n, x, &one, y, &one )

NOTE:

Intel® oneAPI Math Kernel Library (oneMKL) has both upper-case and lower-case entry points in the Fortran-style (case-insensitive) BLAS, with or without the trailing underscore. So, all these names are equivalent and acceptable:cdotc, CDOTC, cdotc_, and CDOTC_.

The above example shows one of the ways to call several level 1 BLAS functions that return complex values from your C and C++ applications. An easier way is to use the CBLAS interface. For instance, you can call the same function using the CBLAS interface as follows:

cblas_cdotc( n, x, 1, y, 1, &result )

NOTE:

The complex value comes last on the argument list in this case.

The following examples show use of the Fortran-style BLAS interface from C and C++, as well as the CBLAS (C language) interface:

Example "Calling a Complex BLAS Level 1 Function from C"

The example below illustrates a call from a C program to the complex BLAS Level 1 function zdotc(). This function computes the dot product of two double-precision complex vectors.

In this example, the complex dot product is returned in the structure 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;
}

In this example, the complex dot product for large data size is returned in the structure 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;
 }

Example "Calling a Complex BLAS Level 1 Function from C++"

Below is the C++ implementation:

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

Example "Using CBLAS Interface Instead of Calling BLAS Directly from C"

This example uses 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;
}