Currently, the following Intel® oneAPI Math Kernel Library (oneMKL) types are defined in the mkl_types.h header file:
MKL_INT - for integer values
MKL_UINT - for unsigned integer values
MKL_Complex8 - for single precision complex values (a structure that contains single precision real and imaginary parts
real
and imag
)MKL_Complex16 - for double precision complex values (a structure that contains double precision real and imaginary parts
real
and imag
)See the oneMKL User's Guide and the mkl_types.h header file for more details.
The types listed above can be redefined in oneMKL version 10.3 update 4 so that C/C++ developers can avoid explicit argument casting when calling the library in applications that use the types "binary compatible" with those in oneMKL.
Such a possibility is often needed because the user can use his or her own types that can be "binary compatible", that is, having the same representation or memory layout.
For example:
- ISO C99 Complex type qualifier
_Complex
- C++ Complex types std::complex
- There are several integer types on Linux* OS for ILP64, for example:
__int64
,
long
orlong long
Another way to do this is to use the compiler option -D<name>=<username>, for example:
#define MKL_INT size_t
#include "mkl.h"
or
add the compiler option "-DMKL_INT=size_t" in the command line or build configuration.
Inaccurate redefinition of the oneMKL types may result in unpredictable computational results and/or crash of the application if the user's data types and those of oneMKL turn out to be incompatible (*). It is the user's responsibility to make a thorough analysis of such cases before redefining data types in oneMKL.
An example of incorrect redefinition for the oneMKL integer data type: #define MKL_INT double
An example of correct redefinition of MKL_INT for ILP64 if positive integer values less than 2^63 are used:
#define MKL_INT size_t
Below is a short C++ example zhetrd.cpp on the Linux OS and Windows, that covers the correct redefinition of MKL_Complex16
and MKL_INT:
#include <stdio.h>
#define MKL_ILP64 // in order to use size_t instead of MKL_INT
#if 1 // to use user-defined MKL_INT and MKL_Complex16
#define FLEXCOMPLEX
typedef size_t INT;
#define MKL_INT INT // this tells MKL about user's MKL_INT type
#ifdef _WIN32
#include <complex>
typedef std::complex<double> DCOMPLEX;
#else
typedef double _Complex DCOMPLEX;
#endif
#define MKL_Complex16 DCOMPLEX // this tells MKL about user's MKL_Complex16 type
#else // using MKL default types MKL_INT and MKL_Complex16
#define DCOMPLEX MKL_Complex16
#define INT MKL_INT
#endif
#include "mkl.h"
/* Auxiliary routine: printing a vector of doubles */
void print_vector_of_doubles( char* desc, int n, double* a ) {
int i;
printf( "%sn", desc );
for( i = 0; i < n; i++ ) printf( " %.4g", a[i] );
printf( "n" );
}
/* Parameters */
#define SIZE 4
#define LDA SIZE
#define LWORK (64*SIZE)
#define UPLO "Low"
int main(void) { // based on NAG F08FSF example
/* Locals */
INT n = SIZE;
INT lda = LDA;
INT lwork = LWORK;
INT info = 1000;
/* Local arrays */
DCOMPLEX A[LDA*SIZE] = {
#ifdef FLEXCOMPLEX
#ifdef _WIN32
DCOMPLEX(-2.28, 0.00), DCOMPLEX( 1.78, 2.03), DCOMPLEX( 2.26,-0.10), DCOMPLEX(-0.12,-2.53),
DCOMPLEX( 1.78, 2.03), DCOMPLEX(-1.12, 0.00), DCOMPLEX( 0.01,-0.43), DCOMPLEX(-1.07,-0.86),
DCOMPLEX( 2.26,-0.10), DCOMPLEX( 0.01,-0.43), DCOMPLEX(-0.37, 0.00), DCOMPLEX( 2.31, 0.92),
DCOMPLEX(-0.12,-2.53), DCOMPLEX(-1.07,-0.86), DCOMPLEX( 2.31, 0.92), DCOMPLEX(-0.73, 0.00)
#else
-2.28+__I__*0.00, 1.78+__I__*2.03, 2.26-__I__*0.10, -0.12-__I__*2.53,
1.78+__I__*2.03, -1.12+__I__*0.00, 0.01-__I__*0.43, -1.07-__I__*0.86,
2.26-__I__*0.10, 0.01-__I__*0.43, -0.37+__I__*0.00, 2.31+__I__*0.92,
0.12-__I__*2.53, -1.07-__I__*0.86, 2.31+__I__*0.92, -0.73+__I__*0.00
#endif
#else // struct MKL_Complex16
{-2.28, 0.00}, { 1.78, 2.03}, { 2.26,-0.10}, {-0.12,-2.53},
{ 1.78, 2.03}, {-1.12, 0.00}, { 0.01,-0.43}, {-1.07,-0.86},
{ 2.26,-0.10}, { 0.01,-0.43}, {-0.37, 0.00}, { 2.31, 0.92},
{-0.12,-2.53}, {-1.07,-0.86}, { 2.31, 0.92}, {-0.73, 0.00}
#endif
};
DCOMPLEX TAU[SIZE-1];
DCOMPLEX WORK[LWORK];
double D[SIZE];
double E[SIZE-1];
zhetrd_(UPLO, &n, A, &lda, D, E, TAU, WORK, &lwork, &info);
if (!info) {
print_vector_of_doubles( "Diagonal", SIZE, D);
print_vector_of_doubles( "Off-diagonal", SIZE-1, E);
} else
printf( "FAILEDn" );
return 0;
}
Use the following on the Linux OS with the Intel® compiler:
icpx zhetrd.cpp -lmkl_rt -lpthread
and the next example illustrates linking that uses Intel® compilers on the Window OS.
icl zhetrd.cpp mkl_rt.lib /Qopenmp
Use the command below to output result:
./a.out
The result:
Diagonal
-2.28 -0.1285 -0.1666 -1.925
Off-diagonal
-4.338 -2.023 -1.802
(*) this feature is intended for advanced users