Boost logo

Ublas :

Subject: [ublas] numeric-bindings: current issues on 64-bit platforms
From: Thomas Klimpel (Thomas.Klimpel_at_[hidden])
Date: 2008-11-30 14:27:11


Thomas Klimpel wrote:
> Good to hear. So I should probably try to do something about gbsv and gels*.
> When this is done, I would like to change the type used to bind against
> fortran integer from "int" to a typedef like "integer_t", because "int" is
> not always the correct type on 64 platforms.
> However, I will discuss this issue in a separate mail.

Well, i still haven't done something about gbsv and gels*, but I finally managed to get closer to a solution for the issues on 64-bit platforms. It looks like I need two "external" definitions and one internal typedef. The test_fortran_bindings.cpp in the attached zip-archive uses the following:

BIND_FORTRAN_INTEGER_8
BIND_FORTRAN_F2C_RETURN_CONVENTIONS

#ifndef BIND_FORTRAN_INTEGER_8
typedef int integer_t ;
#else
typedef std::ptrdiff_t integer_t ;
#endif

So I would propose to use these names and the corresponding strategy.

Thomas Klimpel wrote:
> I should definitely start another thread to describe the current issues
> on 64-bit platforms and the ideas of how to address them.
> Because of lack of time, I often don't even know whether it is the
> numeric bindings library that is causing the problems,
> or the interoperability between fortran and c++ compiler.
> When I use g77 to compile lapack and gcc-4.2 to compile the c++ code using the
> bindings, I seem to be unable to get the value returned from a fortran FUNCTION.
> I might try compiling lapack with gfortran instead, but I didn't find the time
> to do this. When I said it would be important to address the "backlog",
> I was mostly referring to the fact that I don't even spend enough
> time do these "trivial" things.

It is indeed the bindings library that is causing the problems. The following excerpt from the gfortran manpage explains the problem:

       -ff2c
           Generate code designed to be compatible with code generated by g77 and f2c.

           The calling conventions used by g77 (originally implemented in f2c) require functions that return type default "REAL" to actually
           return the C type "double", and functions that return type "COMPLEX" to return the values via an extra argument in the calling sequence
           that points to where to store the return value. Under the default GNU calling conventions, such functions simply return their results
           as they would in GNU C---default "REAL" functions return the C type "float", and "COMPLEX" functions return the GNU C type "complex".
           Additionally, this option implies the -fsecond-underscore option, unless -fno-second-underscore is explicitly requested.

And g77 has a corresponding -fno-f2c option. Neither currently works with the bindings on 64-bit systems, because 'that return type default "REAL" to actually return the C type "double"' is ignored, but 'that return type "COMPLEX" to return the values via an extra argument in the calling sequence that points to where to store the return value' is respected. I don't really understand why this works on 32-bit systems, but...

The test_fortran_bindings.sh shows that this solves the issues on linux64. Here is it's output:
integer_8: 0 f2c_return_conventions: 1
ireal(-2): -1
sreal(-2): -1
dreal(-2): -1
creal(-2): -1
zreal(-2): -1
integer_8: 0 f2c_return_conventions: 0
ireal(-2): -1
sreal(-2): -1
dreal(-2): -1
creal(-2): -1
zreal(-2): -1
integer_8: 0 f2c_return_conventions: 0
ireal(-2): -1
sreal(-2): -1
dreal(-2): -1
creal(-2): -1
zreal(-2): -1
integer_8: 0 f2c_return_conventions: 1
ireal(-2): -1
sreal(-2): -1
dreal(-2): -1
creal(-2): -1
zreal(-2): -1
integer_8: 1 f2c_return_conventions: 0
ireal(-2): -1
sreal(-2): -1
dreal(-2): -1
creal(-2): -1
zreal(-2): -1
integer_8: 1 f2c_return_conventions: 1
ireal(-2): -1
sreal(-2): -1
dreal(-2): -1
creal(-2): -1
zreal(-2): -1

However, something is still fishy, because the test-script produces the following output on a linux32 system:
integer_8: 0 f2c_return_conventions: 1
ireal(-2): -1
sreal(-2): -1
dreal(-2): -1
creal(-2): -1
zreal(-2): -1
integer_8: 0 f2c_return_conventions: 0
ireal(-2): -1
sreal(-2): -1
dreal(-2): -1
creal(-2): 1.4013e-45
zreal(-2): -1
integer_8: 0 f2c_return_conventions: 0
ireal(-2): -1
sreal(-2): -1
dreal(-2): -1
creal(-2): 1.4013e-45
zreal(-2): -1
integer_8: 0 f2c_return_conventions: 1
ireal(-2): -1
sreal(-2): -1
dreal(-2): -1
creal(-2): -1
zreal(-2): -1
integer_8: 1 f2c_return_conventions: 0
ireal(-2): 2147483647
sreal(-2): -1
dreal(-2): -1
creal(-2): 1.4013e-45
zreal(-2): -1
integer_8: 1 f2c_return_conventions: 1
ireal(-2): 2147483647
sreal(-2): -1
dreal(-2): -1
creal(-2): -1
zreal(-2): -1

So I still have to find out why linux32 behaves different than I thought it would from the descriptions in the manpage.

Regards,
Thomas