Intel® oneAPI Math Kernel Library
Ask questions and share information with other developers who use Intel® Math Kernel Library.

complex data type in MKL

Dan4
Beginner
1,884 Views
Dear all,

I want to use MKL functions for matrices which contain complex data types (real with imaginary parts). I have read "The C++ std::complex type can now be used instead of MKL-specific complex types". Now I want to use C++ "complex" data type instead of MKL_Complex16 data type.

I found a link (http://software.intel.com/sites/products/documentation/hpc/mkl/lin/MKL_UG_coding_calls/Using_Complex_Types_in_C_C.htm) that explain how one can use C++ complex data type instead of MKL's and it says that it can be done like this:

#include

#include

#define MKL_Complex16 std::complex

#include "mkl.h"

Now the problem is when I define MKL_Complex16 in my code:

#include "simprofile.h"
#include "model.h"
#include "MatrixPrinter.h"
#include "subdivision.h"
#include "signature.h"

#define MKL_Complex16 std::complex

#include "mkl.h"
#include "mkl_spblas.h"
#include "mkl_trans.h"

But when I compile the code I get this error:

../include/mkl_types.h(43): error: expected a ";"
} MKL_Complex16;
^
../include/mkl_types.h(43): warning #64: declaration does not declare anything
} MKL_Complex16;

Does anybody know how can I fix this problem? It is extremely important for me to use C++ complex data type and not MKL's type.

Thanks,

D.

0 Kudos
14 Replies
Dmitry_B_Intel
Employee
1,884 Views
Hi D.

The error message that you've shown indicates you are using MKL version older than10.2.x.
Let me advise you to upgrade your MKL version to the latest available.

Alternatively you may try to #include "mkl_types.h" just before you #define MKL_Complex16 in your program, like this:

#include "mkl_types.h"
#define MKL_Complex16 std::complex
#include "mkl.h"
#include "mkl_spblas.h"
#include "mkl_trans.h"

This should work.
Thanks
Dima
0 Kudos
mecej4
Honored Contributor III
1,884 Views
Dmitry has suggested one cure. Here is another.

Your redefinition of MKL_Complex16 conflicts with the type definition in the MKL header files.

You should have written
[cpp]#define MKL_Complex16 std::complex[/cpp]
instead of
[bash]#define MKL_Complex16 
std::complex[/bash]
(It is not certain that you did so in your code).

Another way is to use the code from the MKL manual without change, but use a preprocessor definition in the compilation command, as in

[bash]icc -DMKL_Complex16="std::complex" ...[/bash]

0 Kudos
Dan4
Beginner
1,884 Views
Well, I tried to use compiler command line command which is -DMKL_Complex16="std::complex", but I still same error which was:

../include/mkl_types.h(43): error: expected a ";"
} MKL_Complex16;
^

../include/mkl_types.h(43): warning #64: declaration does not declare anything
} MKL_Complex16;


I use Intel C++ compiler version 11.1 under Linux and I compile my code using following compiler switches

icpc -DHAVE_CONFIG_H -I. -I.. -I../include -DNOGMM_VERIFY -DUSE_OPENMP -DMKL_Complex16="std::complex" -O1 -ipo0 -fp-model precise -openmp -vec-report -par-report -openmp-report -DMKL_VML_MIXED -MT comp_wrapper.o -MD -MP -MF .deps/comp_wrapper.Tpo -c -o comp_wrapper.o comp_wrapper.cpp

then I get the error above. Why it is like that? Do you get same erorr as well? Intel MKL is supposed to use C++ standard data type for complex but how?

Thanks,

D.
0 Kudos
mecej4
Honored Contributor III
1,884 Views
Well, we have not seen a "reproducer" (a small self-contained code extract which is just large enough to reproduce the reported error), so the question "Do you get same error?" cannot be answered.

Do note, however, that the flagged error is in a system include file (mkl_types.h), and not in your source code. That is a sure sign of not having the preprocessor symbols defined properly, or not listing the system include files in proper sequence in your code.
0 Kudos
Dmitry_B_Intel
Employee
1,884 Views

Hi all,

What mecej4 proposed in the third post is essentialy the same what D did in the first place.

The point of solution is: include mkl_types.h first, then define MKL_Complex16 to whatever you need and include "mkl.h" and other header files after that. Please refer to the second post for the example.

Thanks
Dima

0 Kudos
Dan4
Beginner
1,884 Views
But I thought if I use compiler command line (-DMKL_Complex16="std::complex") , there is no need to define any preprocessor/compiler directive because the compiler will know what type is used . Am I right or should I still use any compiler preprocessor? I read in Intel MKL user guide:

Intel MKL provides complex types MKL_Complex8 and MKL_Complex16, which are
structures equivalent to the Fortran complex types COMPLEX(4) and COMPLEX(8),
respectively. These types are defined in the mkl_types.h header file. You can use these
types to define complex data. You can also redefine the types with your own types before
including the mkl_types.h header file. The only requirement is that the types must be
compatible with the Fortran complex layout, that is, the complex type must be a pair of
real numbers for the values of real and imaginary parts.
For example, you can use the following definitions in your C++ code:
#define MKL_Complex8 std::complex
and
#define MKL_Complex16 std::complex .
See Example 7-2 for details. You can also define these types in the command line:
-DMKL_Complex8="std::complex"
-DMKL_Complex16="std::complex".

so I guess the command line defining should be enough or am I wrong?

Thanks,

D.

0 Kudos
mecej4
Honored Contributor III
1,884 Views
Preprocessing is not covered by the Fortran standards, and how/if preprocessing is done is processor dependent. Perhaps the following example will illustrate the matter:

[fortran]program tst
integer :: x,y
x=3; y=4
write(*,*)x/y
end program tst
[/fortran]
If I call this file tst.f90 and compile as follows

[bash]ifort tst.f90; ./a.out[/bash]
I get the result printed as 0. If, then, I try

[bash]ifort -Dinteger=real tst.f90[/bash]
I get 0 again. However, if I compile using

[bash]ifort -fpp -Dinteger=real tst.f90[/bash]
I get the result 0.75.

The Intel compiler will run the code through the preprocessor only if (i) the file is named tst.F90, in which case the capital F tells the compiler to run the preprocessor, or (ii) the -fpp compiler option is used, which asks that the preprocessor be used even though the file extension is merely .f90.

With the second version that I listed, the preprocessor is not called even though there is a -Dxxx=yyy option in the command.
0 Kudos
TimP
Honored Contributor III
1,884 Views
Quoting mecej4
Preprocessing is not covered by the Fortran standards, and how/if preprocessing is done is processor dependent. Perhaps the following example will illustrate the matter:

Well, there is a (relatively obscure) Fortran standard on pre-processing, commonly referred to as coco, but it doesn't match the requirements of OpenMP, which clearly must be satisfied by the ifort fpp, but don't come into play for your example. The issue doesn't appear relevant to MKL. If you truly want somewhat portable pre-processing, you have the option of setting up a Makefile to use 'gcc -traditional -E -x c yourfile > yourpreprocessedfile' or some similar tactic.
0 Kudos
Dan4
Beginner
1,884 Views

So is it same for Intel C++ compiler too, because I do use Intel C++ compiler and not Fortran? I mean can it be because I am not using "-fpp" during my compilation?

D.
0 Kudos
TimP
Honored Contributor III
1,884 Views
Pre-processing with Intel C++ ought to be compatible with the active g++, except for differences in default include paths and the like. It's not the same preprocessor as the one invoked by ifort -fpp.
0 Kudos
mecej4
Honored Contributor III
1,884 Views
Danltu.se,

I'm sorry, I can see now that what I wrote earlier may have misled you.

Since the excerpts from the MKL documentation mentioned Fortran, I guessed (incorrectly) that you had a mix of Fortran and C++ sources. It is now becoming clear that you have only C++ sources. However, the libraries that you are calling are Fortran based.

In Fortran, it is infrequent that source code needs a preprocessor run. In fact, the use of modules is recommended over using file includes. That is why it is necessary to use the -fpp option, or to use upper case .F90 as the file extension, when preprocessing is needed.

In C++ (and C) the preprocessor is needed almost always, even for a 'Hello World!' program, so invoking the preprocessor is the default, and quite often the preprocessor is built into the front end of the C++ compiler.

Now, for your original question: what Dmitry wrote concerning older versions of MKL ("#include "mkl_types.h" just before you #define MKL_Complex16") conflicts with the manual for the current version of MKL ("You can also redefine the types with your own types before including the mkl_types.h header file"). The order of the #define and the #include are opposites for the two versions!

Forget about explicitly calling the preprocessor, etc. Try

(i) following Dmitry's prescription with the old version of MKL that you have

(ii) If (i) fails, try the current version of MKL, following what the current MKL manual tells you to do.

Sorry for causing confusion!
0 Kudos
Dmitry_B_Intel
Employee
1,884 Views
Yes, the reason why the solution I suggested conflicted with the manual is version difference. However, the soution, or a trick, to name itbetter will work. It may be adjusted to work correctly with both older and newer versions of MKL, like this:

#include "mkl_types.h"
// now MKL_Complex16 is defined. It may be typedefed or #defined, in general.
// We don't care because we'll use our own *compatible* complex type later.

#undef MKL_Complex16
// In case it was #defined, tell the preprocessor forget the definition

#define MKL_Complex16 mycompatiblecomplextype
// In case it was typedefed, tell the preprocessor replace its uses with ours.

#include "mkl.h"
// Now mkl.h will see our type in the declarations of functions.
// Since the type is compatible, it causes no issues.
// mkl_types.h will not revert our definition because we've already included it above
//and it prevents double inclusion.


Except the minor '#undef' this is what I suggested earlier, though I didn't explain it well, sorry.

Thanks
Dima
0 Kudos
mecej4
Honored Contributor III
1,884 Views
Dmitry,

Thanks for the clarifications. Another trick, one which is routinely used in system header files, is something along the lines of

[cpp]#ifndef MKL_Complex16
#define MKL_Complex16 xxxxxxx (put the MKL default definition here)
#endif[/cpp]
This version will also give us independence from order of header file inclusion, but does not require the user to issue #undef in user code.
0 Kudos
Dmitry_B_Intel
Employee
1,884 Views
Right. This had already been implemented in a version of MKL later than that D. used originally.
0 Kudos
Reply