3

For interoperability with C programs, the 2003 revision of the Fortran standard introduced a module iso_c_binding, which allows one to write things like this:

USE iso_c_binding, ONLY: c_int, c_float
INTEGER(KIND=c_int) :: x
REAL(KIND=c_float) :: y

which is guaranteed to map exactly to a int x and a float y on the C-side. Now for integers, this is crucial since the default INTEGER type may (depending on compiler and platform) very well wrap to a 64-bit integer type even when int is 32-bit.

However, for floating point types, the following mappings seem almost unavoidable:

REAL*4  (or)  REAL               ->  float
REAL*8  (or)  DOUBLE PRECISION   ->  double

So here's the question: Is there any practical platform or compiler where this is not satisfied, e.g., where sizeof(REAL*4) != sizeof(float)?

jbdv
  • 1,263
  • 1
  • 11
  • 18
summentier
  • 456
  • 4
  • 13
  • 1
    The question seems to overlook the C binding's kind constants for *real* types. If one wanted to map a C `double`, the standard way would be `REAL(KIND = C_DOUBLE) :: a_double`. Similar for mapping C `float`s. It is therefore ***by no means*** necessary to make assumptions about how `DOUBLE PRECISION` and default `REAL` map. – John Bollinger Mar 22 '19 at 11:58
  • 1
    I agree with @JohnBollinger's comment, but I assume the question is motivated by "why do we need `real(c_float) for_c` rather than just `real for_c`?". Is that correct? – francescalus Mar 22 '19 at 12:00
  • ... and if so, would you please edit the question to clarify, especially the part about "almost unavoidable" use of default real and DP kinds to map C floating-point types? – John Bollinger Mar 22 '19 at 12:03
  • You must also count with the possibility that their `sizeof` is the same, but they are different datatypes. Even `int` can have the same `sizeof` as a `float`, but internally they are different. Notably, an extended precision REAL*10 is stored in whole words in memory, so in 128 bits, but a quadruple precision REAL*16 is stored in the same 128 bits. – Vladimir F Героям слава Mar 22 '19 at 13:30
  • @francescalus of course ... that was the whole point that you of course do mapping for real types as well using `iso_c_binding`. The question is, do I need to do that in practice? – summentier Mar 22 '19 at 14:01
  • 1
    @summentier Yes, you should do that. Anytime somene might compile your code with some (perfectly standar conforming) options, that change the default kinds. If you have default 8-byt integer, to remain standard conforming you should also use 8-byte reals and logicals. Even if not, many people compile codes with these promotion flags, just search among the questions on this site. You never know who and how will compile your code. – Vladimir F Героям слава Mar 22 '19 at 14:07

2 Answers2

7

Consider gfortran which has the compile-time options -freal-4-real-8, -freal-8-real-16, etc. These change the size of a Fortran real, including those declared with the non-standard real*4.

Consider also ifort:

  use, intrinsic :: iso_c_binding
  print*, C_SIZEOF(0._c_double).eq.C_SIZEOF(0d0)
end program

compiled with/without -double-size 128 I see F/T.

Of course, as Vladimir F has commented, even excluding the size of the types there is more to consider in terms of interoperability. It really is desirable to use real(c_double) ... to give an interoperable real.

francescalus
  • 30,576
  • 16
  • 61
  • 96
3

Depends on your idea of "practical compiler", I guess.

Neither the C standard nor the Fortran standard require IEEE conformance, but most[citation needed] compilers adhere to it (as do most processors, so this is as much a matter of optimization as it is of conformance). Cray and VAX processors are the notable exceptions, so you may find a compiler for those systems that conforms to the processor's implementation of float instead. (e.g., on a Cray, a float is 8 bytes).

For more: http://www.quadibloc.com/comp/cp0201.htm

L. Scott Johnson
  • 4,213
  • 2
  • 17
  • 28
  • 1
    There is really more to it. It is really not dissimilar to integers, where Fortran integer can be twice as big as C int. – Vladimir F Героям слава Mar 22 '19 at 18:04
  • On Cray Vector systems a float was 8 bytes. On most of their other products, and certainly all the recent ones I am aware of, a float is 4 bytes. I don't think Cray have produced vector systems in over 10 years. – Ian Bush Mar 22 '19 at 18:23
  • @VladimirF Yes, there are many details about compilers that one can spend a lot of time investigating. But for the OP's question about the size of fortran's REAL*4 compared to the size of C's float, this answer is suitable, I think. – L. Scott Johnson Mar 22 '19 at 18:23
  • What is missing is the key consideration while both languages are extremely likely to use the same IEEE float, double, ... They may well differ (even in practise) in which one of these IEEE types they call C float, C double, Fortran real and Fortran double precision. Fortran real might well be different from Fortran real*4 (if the compiler supports this nonstandard thing at all). – Vladimir F Героям слава Mar 23 '19 at 08:03