The LAPACK forum has moved to https://github.com/Reference-LAPACK/lapack/discussions.

complex level 1 BLAS functions and c(++)

Open discussion regarding features, bugs, issues, vendors, etc.

complex level 1 BLAS functions and c(++)

Postby Klaas » Tue Sep 04, 2007 8:19 am

Dear all,

I have a question that has been puzzling me for some time now. It regards the calling of a complex fortran function returning a complex value. (example cdotc ).

When you have a fortran compiled blas library, the general rule to call it is doing the following changes
Code: Select all
real -> float
doublereal -> double
complex -> typedef struct { float r, i; } complex or just std::complex<float>
doublecomplex -> typedef struct { double r, i; } doublecomplex or just std::complex<double>

and everything becomes a pointer

if the fortran routine is a subroutine, the c translation becomes a function returning a void
if the fortran routine is a function returning a value, the c function returns the same translated type.

So this is all very nice and works fine
an example here is scopy which becomes then in c++
Code: Select all
extern "C" {
void scopy_(long *, float *, long *, float *, long *);
}

or zcopy is then
Code: Select all
extern "C" {
void zcopy_(long *, std::complex<double> *, long *, std::complex<double> *, long *);
}


Now this is nice, I have no problems with the above, but here is the thing that puzzles me. When addressing a fortran function (example sdot and cdotc) there apears a difference between returning a complex value or not. a real or doublereal has to be defined like this
Code: Select all
extern "C" {
float sdot_(long *, float *, long *, float *, long *);
}


while a complex can not return a complex but must be defined as a void

Code: Select all
extern "C" {
void cdotc_(std::complex<float> *result, long *, std::complex<float> *, long *, std::complex<float> *, long *);
}


What is the reason of this difference? Why cant I return a complex value, or even why can't i define a real function analogue to the complex one. The following two give sporadic seg faults, and never the correct result
Code: Select all
extern "C" {
void sdot_(float *result, long *, float *, long *, float *, long *);
std::complex<float> cdotc_(long *, std::complex<float> *, long *, std::complex<float> *, long *);
}


Thanks
Klaas
Klaas
 
Posts: 22
Joined: Mon Feb 06, 2006 2:06 pm

Postby Klaas » Mon Oct 01, 2007 8:26 am

for the interested people, I have found the answer to this question in a newsgroup.

Between the caller values on the stack and callee values on the
stack, there is interleaved section for the function call/return
protocol. On return, the function results has to be moved over
linkage into the caller values. If the result value fits in the
registers, (such as integer or double precision), the result is
loaded there and the return executed with the caller able to
deposit the result where it wants.

If the results cannot fit in the registers due to size or brain
dead calling conventions, it typically has to be copied by the callee
to a preallocated slot in the caller; the address has to be passed

Regards
Klaas
Klaas
 
Posts: 22
Joined: Mon Feb 06, 2006 2:06 pm


Return to User Discussion

Who is online

Users browsing this forum: No registered users and 4 guests