I am running into an inconsistency in the header file mkl.h for BLAS functions being called from C. I finally used the "/E" option from the C compiler to dump the pre-processed source so I could inspect it.
Here are 2 examples of what I find in the header files:
void dgemm(const char *transa, const char *transb, const int *m, const int *n, const int *k,
const double *alpha, const double *a, const int *lda, const double *b, const int *ldb,
const double *beta, double *c, const int *ldc);
int lsame(const char *ca, const char *cb, const int lca, const int lcb);
If I look at the original NetLib definition of these 2 functions - i.e., their FORTRAN equivalents - the dgemm header matches the FORTRAN call. That is, there are no extra arguments to the C header to deal with character strings.
However, the lsame function is NOT like that. The string length of both ca and cb is added to the end of the argument list. Clearly, this is causing a problem in my code as I'm not sure how each function is to be called from within a C program.
Can somebody enlighten me on how the standard FORTRAN NetLib API is modified for C when using "mkl.h"? Thanks.
Those headers imply that MKL is built with the equivalent of Fortran USE iso_c_binding, or at least are available to use that way.
If you call MKL LSAME from C (why?) you should be OK if you are consistent with the mkl .h. The question arises how Fortran calls are handled without iso_c_binding. This could get into system-dependent questions if the library isn't built to handle both kinds of Fortran calls; ignoring the issue, as Netlib seems to do, could fail on some systems.
Netlib BLAS predates the availabilty of iso_c_binding, but it looks like an inconsistency between those headers.
As the functions work only for single characters, it probably doesn't matter whether those characters are followed by '\0' as long as you don't depend on it.
Thanks for the quick reply.
It would be helpful if you could provide me with a link to some documentation for how to call these 2 functions from a C program. The problem I run into is that if I call LSAME without the last 2 arguments (the length of each string), I get compilation errors because my function call does not match the prototype.
It does not matter to me whether I need to add the string lengths at the end of the call as long as I know to add them to all functions that have string arguments. My problem is that the string length seems to be added to some prototypes but not others. If this is a bug on LSAME, so be it; I can work around this specific function. But if this is a more pervasive issue - string lenghts in some but not in other functions - then I would like to know whether there's any logic to this.
There is indeed inconsistency in declarations of certain functions using Fortran CHARACTER argument in mkl_blas.h header. Dgemm() should have been declared with the length arguments like lsame() is. However, both functions check only the first characters of the string arguments and effectively ignore the length argument. Fortran - C interoperability guidance is "A Fortran character string with a length other than 1 is not interoperable."
First of all, thanks to all that replied.
Ying, I don't see a segmentation fault or a crash of any kind. The issue is more of a uniformity than anything else. BLAS functions are standardized in their arguments - at least, the FORTRAN API.
When making these functions available in C/C++ I assumed that I could just look at the FORTRAN API and, if there are strings, we either add the string lengths at the end of the argument list or we don't. I expected this to be the case in all functions.
But I was getting compilation errors with my calls to LSAME in a C program - and only on LSAME! - and couldn't figure out why. The error did mention the number of arguments was incorrect, and I kept referring back to the FORTRAN interface assuming that I could figure out everything from that. But that was not the case. This function happens to be different from the other BLAS functions I'm using: the string arguments are treated differently than DGEMM on the C interface.
I finally searched for the function declaration in the header file and that's when I noticed that string lengths were added to LSAME, but not to DGEMM. That's why I was getting compiler errors.
I have macros that deal with these headers - in case users are using MKL or not. Of course, almost 100% are using MKL BLAS, but I needed to cover the few that were not. Assuming that MKL did not add the string lengths my macros did not add them to MKL. But this general rule failed in LSAME and I had to abandon my generic macro and explicitly define what I needed for each function since there were exceptions to the rule.
A question: you mention the MKL manual entry for "lsame". Could you send me a link to that? I haven't been able to find that. Thanks.
Not all Fortran compilers treat CHARACTER arguments the same without USE iso_c_binding the same, so you necessarily run into potential incompatibility there between Fortran and C. Many of the platforms where people build their own BLAS may not care whether you ignore or deal with potential implicit trailing arguments, but some will. As the reference source was last updated in 1994, there was no one solution to this.
LSAME seems to date back to Fortran 66, where the implementation was not at all portable, I don't know why you would call LSAME from user code with any recent C or Fortran.
We do use lapack and blas in our software. We ship libraries to our users, and not end-user applications. As a result, we refer our users to Intel as the place to get these libraries.
However, at times - especially during basic evaluations of our software where only functionality is an issue, not performance - we need to include our own F2C version of these libraries so users can evaluate our software. We control which libraries are being used with #ifdef in our header files. That's where the macros come from. And standard F2C translation of these libraries include LSAME calls to them, so we need to include them also. Our software does not call LSAME - as you pointed out! - but our unoptimized version of the blas and lapack do, so we need to have them there. And, sometimes, users have one but not the other of these libraries.
I know... it's confusing and not very efficient, but we must deal with the market as it is, not as we wish it to be. And it's not perfect out there :-(.
I've made the exception for LSAME. All should be working now.
Thanks to all!
Thanks for the explanation. I also add some notes from our developer for your reference.
In BLAS and LAPACK Fortran interfaces only functions lsame(), xerbla(), and mkl_progress() are declared with the implicit length arguments shown explicitly. Of them only lsame() interprets the CHARACTER argument as CHARACTER*1, that is only lsame() may ignore the implicit length argument. Surprisingly, function lsamen() does not show implicit length arguments in the prototypes, probably because it has explicit argument n. For functions xerbla() and mkl_progress() the character arguments are arbitrary length strings and they need the length arguments.