In this case gfortran is internally representing your hexadecimal ("Z") literals as the largest unsigned integer size available. Since transfer
is a Fortran intrinsic, and Fortran does not have unsigned integers, the first thing gfortran does is to assign the literal to a signed type, which causes your bit pattern for negative infinity to overflow. This happens in many other cases where you use BOZ literals, and I think that this is a bug in gfortran.
I think this only shows up on a 32 bit system because on your 64 bit system, gfortran probably has a 128 bit integer type available; a 128 bit signed integer will not "overflow" with that bit pattern.
But it is also the case that your code does not conform to the Fortran standard, which says that hex literals can only appear inside data
statements or the functions int
, real
, or dble
. However, putting a hex literal in dble
does the same thing as transfer
anyway. If gfortran did not have a bug in it, your program would work, but it would technically be incorrect.
Anyway, the following code works for me in gfortran, and I believe it will solve your problem in a way that's standard-compliant and avoids -fno-range-check
:
integer, parameter :: i8 = selected_int_kind(13)
integer, parameter :: r8 = selected_real_kind(12)
integer(i8), parameter :: foo = int(Z'7FF0000000000000',i8)
integer(i8), parameter :: bar = ibset(foo,bit_size(foo)-1)
real(r8), parameter :: posinf = transfer(foo,1._r8)
real(r8), parameter :: neginf = transfer(bar,1._r8)
print *, foo, bar
print *, posinf, neginf
end
Output:
9218868437227405312 -4503599627370496
Infinity -Infinity
The key is to create the pattern for positive infinity first (since it works), and then create the pattern for negative infinity by simply setting the sign bit (the last one). The ibset
intrinsic is only for integers, so you then have to use transfer
on those integers to set your real positive/negative infinity.
(My use of i8/r8 is just habit, since I've worked with compilers where the kind parameter was not equal to the number of bytes. They are both equal to 8 in this case.)